home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / vidhrdw / vector.c < prev    next >
C/C++ Source or Header  |  2000-05-13  |  24KB  |  970 lines

  1. /******************************************************************************
  2.  *
  3.  * vector.c
  4.  *
  5.  *
  6.  * Copyright 1997,1998 by the M.A.M.E. Project
  7.  *
  8.  *        anti-alias code by Andrew Caldwell
  9.  *        (still more to add)
  10.  *
  11.  * 980611 use translucent vectors. Thanks to Peter Hirschberg
  12.  *        and Neil Bradley for the inspiration. BW
  13.  * 980307 added cleverer dirty handling. BW, ASG
  14.  *        fixed antialias table .ac
  15.  * 980221 rewrote anti-alias line draw routine
  16.  *        added inline assembly multiply fuction for 8086 based machines
  17.  *        beam diameter added to draw routine
  18.  *        beam diameter is accurate in anti-alias line draw (Tcosin)
  19.  *        flicker added .ac
  20.  * 980203 moved LBO's routines for drawing into a buffer of vertices
  21.  *        from avgdvg.c to this location. Scaling is now initialized
  22.  *        by calling vector_init(...). BW
  23.  * 980202 moved out of msdos.c ASG
  24.  * 980124 added anti-alias line draw routine
  25.  *        modified avgdvg.c and sega.c to support new line draw routine
  26.  *        added two new tables Tinten and Tmerge (for 256 color support)
  27.  *        added find_color routine to build above tables .ac
  28.  *
  29.  **************************************************************************** */
  30.  
  31. /* GLmame and FXmame provide their own vector implementations */
  32. #if !(defined xgl) && !(defined xfx) && !(defined svgafx)
  33.  
  34. #include <math.h>
  35. #include "osinline.h"
  36. #include "driver.h"
  37. #include "osdepend.h"
  38. #include "vector.h"
  39. #include "artwork.h"
  40.  
  41. #define VCLEAN  0
  42. #define VDIRTY  1
  43. #define VCLIP   2
  44.  
  45. unsigned char *vectorram;
  46. size_t vectorram_size;
  47.  
  48. int antialias;                            /* flag for anti-aliasing */
  49. int beam;                                 /* size of vector beam    */
  50. int flicker;                              /* beam flicker value     */
  51. int translucency;
  52.  
  53. static int beam_diameter_is_one;          /* flag that beam is one pixel wide */
  54.  
  55. static int vector_scale_x;                /* scaling to screen */
  56. static int vector_scale_y;                /* scaling to screen */
  57.  
  58. static float gamma_correction = 1.2;
  59. static float intensity_correction = 1.5;
  60.  
  61. /* The vectices are buffered here */
  62. typedef struct
  63. {
  64.     int x; int y;
  65.     int col;
  66.     int intensity;
  67.     int arg1; int arg2; /* start/end in pixel array or clipping info */
  68.     int status;         /* for dirty and clipping handling */
  69. } point;
  70.  
  71. static point *new_list;
  72. static point *old_list;
  73. static int new_index;
  74. static int old_index;
  75.  
  76. /* coordinates of pixels are stored here for faster removal */
  77. static unsigned int *pixel;
  78. static int p_index=0;
  79.  
  80. static UINT32 *pTcosin;            /* adjust line width */
  81. static UINT8  *pTinten;            /* intensity         */
  82. static UINT16 *pTmerge;            /* mergeing pixels   */
  83. static UINT16 *invpens;            /* maps OS colors to pens */
  84.  
  85. static UINT16 *pens;
  86. static UINT16 total_colors;
  87.  
  88. #define Tcosin(x)   pTcosin[(x)]          /* adjust line width */
  89. #define Tinten(x,y) pTinten[(x)*total_colors+(y)]  /* intensity         */
  90. #define Tmerge(x,y) pTmerge[(x)*total_colors+(y)]  /* mergeing pixels   */
  91.  
  92. #define ANTIALIAS_GUNBIT  6             /* 6 bits per gun in vga (1-8 valid) */
  93. #define ANTIALIAS_GUNNUM  (1<<ANTIALIAS_GUNBIT)
  94.  
  95. static UINT8 Tgamma[256];         /* quick gamma anti-alias table  */
  96. static UINT8 Tgammar[256];        /* same as above, reversed order */
  97.  
  98. static struct osd_bitmap *vecbitmap;
  99. static int vecwidth, vecheight;
  100. static int vecshift;
  101. static int xmin, ymin, xmax, ymax; /* clipping area */
  102.  
  103. static int vector_runs;    /* vector runs per refresh */
  104.  
  105. static void (*vector_pp)(struct osd_bitmap *bitmap,int x,int y,int pen);
  106. static int  (*vector_rp)(struct osd_bitmap *bitmap,int x,int y);
  107.  
  108. /*
  109.  * multiply and divide routines for drawing lines
  110.  * can be be replaced by an assembly routine in osinline.h
  111.  */
  112. #ifndef vec_mult
  113. INLINE int vec_mult(int parm1, int parm2)
  114. {
  115.     int temp,result;
  116.  
  117.     temp     = abs(parm1);
  118.     result   = (temp&0x0000ffff) * (parm2&0x0000ffff);
  119.     result >>= 16;
  120.     result  += (temp&0x0000ffff) * (parm2>>16       );
  121.     result  += (temp>>16       ) * (parm2&0x0000ffff);
  122.     result >>= 16;
  123.     result  += (temp>>16       ) * (parm2>>16       );
  124.  
  125.     if( parm1 < 0 )
  126.         return(-result);
  127.     else
  128.         return( result);
  129. }
  130. #endif
  131.  
  132. /* can be be replaced by an assembly routine in osinline.h */
  133. #ifndef vec_div
  134. INLINE int vec_div(int parm1, int parm2)
  135. {
  136.     if( (parm2>>12) )
  137.     {
  138.         parm1 = (parm1<<4) / (parm2>>12);
  139.         if( parm1 > 0x00010000 )
  140.             return( 0x00010000 );
  141.         if( parm1 < -0x00010000 )
  142.             return( -0x00010000 );
  143.         return( parm1 );
  144.     }
  145.     return( 0x00010000 );
  146. }
  147. #endif
  148.  
  149. static void vector_pp_8(struct osd_bitmap *b,int x,int y,int p)  { b->line[y][x] = p; }
  150. static void vector_pp_16(struct osd_bitmap *b,int x,int y,int p)  { ((unsigned short *)b->line[y])[x] = p; }
  151. static int vector_rp_8(struct osd_bitmap *b,int x,int y)  { return b->line[y][x]; }
  152. static int vector_rp_16(struct osd_bitmap *b,int x,int y)  { return ((unsigned short *)b->line[y])[x]; }
  153.  
  154. /*
  155.  * finds closest color and returns the index (for 256 color)
  156.  */
  157.  
  158. static UINT16 find_pen(unsigned char r,unsigned char g,unsigned char b)
  159. {
  160.     int i,bi,ii;
  161.     long x,y,z,bc;
  162.     ii = 32;
  163.     bi = 256;
  164.     bc = 0x01000000;
  165.  
  166.     do
  167.     {
  168.         for( i = 0; i < total_colors; i++ )
  169.         {
  170.             unsigned char r1,g1,b1;
  171.  
  172.             osd_get_pen(pens[i],&r1,&g1,&b1);
  173.             if((x=(long)(abs(r1-r)+1)) > ii) continue;
  174.             if((y=(long)(abs(g1-g)+1)) > ii) continue;
  175.             if((z=(long)(abs(b1-b)+1)) > ii) continue;
  176.             x = x*y*z;
  177.             if (x < bc)
  178.             {
  179.                 bc = x;
  180.                 bi = i;
  181.             }
  182.         }
  183.         ii<<=1;
  184.     } while (bi==256);
  185.  
  186.     return(bi);
  187. }
  188.  
  189. /* MLR 990316 new gamma handling added */
  190. void vector_set_gamma(float _gamma)
  191. {
  192.     int i, h;
  193.  
  194.     gamma_correction = _gamma;
  195.  
  196.     for (i = 0; i < 256; i++)
  197.     {
  198.         h = 255.0*pow(i/255.0, 1.0/gamma_correction);
  199.         if( h > 255) h = 255;
  200.         Tgamma[i] = Tgammar[255-i] = h;
  201.     }
  202. }
  203.  
  204. float vector_get_gamma(void)
  205. {
  206.     return gamma_correction;
  207. }
  208.  
  209. void vector_set_intensity(float _intensity)
  210. {
  211.     intensity_correction = _intensity;
  212. }
  213.  
  214. float vector_get_intensity(void)
  215. {
  216.     return intensity_correction;
  217. }
  218.  
  219. /*
  220.  * Initializes vector game video emulation
  221.  */
  222.  
  223. int vector_vh_start (void)
  224. {
  225.     int h,i,j,k,c[3];
  226.  
  227.     /* Grab the settings for this session */
  228.     antialias = options.antialias;
  229.     translucency = options.translucency;
  230.     flicker = options.flicker;
  231.     beam = options.beam;
  232.  
  233.     pens = Machine->pens;
  234.     total_colors = MIN(256, Machine->drv->total_colors);
  235.  
  236.     if (Machine->color_depth == 8)
  237.     {
  238.         vector_pp = vector_pp_8;
  239.         vector_rp = vector_rp_8;
  240.     }
  241.     else
  242.     {
  243.         vector_pp = vector_pp_16;
  244.         vector_rp = vector_rp_16;
  245.     }
  246.  
  247.     if (beam == 0x00010000)
  248.         beam_diameter_is_one = 1;
  249.     else
  250.         beam_diameter_is_one = 0;
  251.  
  252.     p_index = 0;
  253.  
  254.     new_index = 0;
  255.     old_index = 0;
  256.     vector_runs = 0;
  257.  
  258.     /* allocate memory for tables */
  259.     pTcosin = malloc ( (2048+1) * sizeof(INT32));   /* yes! 2049 is correct */
  260.     pTinten = malloc ( total_colors * 256 * sizeof(UINT8));
  261.     pTmerge = malloc (total_colors * total_colors * sizeof(UINT32));
  262.     invpens = malloc (65536 * sizeof(UINT16));
  263.     pixel = malloc (MAX_PIXELS * sizeof (UINT32));
  264.     old_list = malloc (MAX_POINTS * sizeof (point));
  265.     new_list = malloc (MAX_POINTS * sizeof (point));
  266.  
  267.     /* did we get the requested memory? */
  268.     if (!(pTcosin && pTinten && pTmerge && invpens && pixel && old_list && new_list))
  269.     {
  270.         /* vector_vh_stop should better be called by the main engine */
  271.         /* if vector_vh_start fails */
  272.         vector_vh_stop();
  273.         return 1;
  274.     }
  275.  
  276.     /* build cosine table for fixing line width in antialias */
  277.     for (i=0; i<=2048; i++)
  278.     {
  279.         Tcosin(i) = (int)((double)(1.0/cos(atan((double)(i)/2048.0)))*0x10000000 + 0.5);
  280.     }
  281.  
  282.     memset (invpens, 0, 65536 * sizeof(unsigned short));
  283.     for( i = 0; i < total_colors ;i++ )
  284.         invpens[Machine->pens[i]] = i;
  285.  
  286.     /* build anti-alias table */
  287.     h = 256 / ANTIALIAS_GUNNUM;           /* to generate table faster */
  288.     for (i = 0; i < 256; i += h )               /* intensity */
  289.     {
  290.         for (j = 0; j < total_colors; j++)               /* color */
  291.         {
  292.             UINT8 r1,g1,b1,pen,n;
  293.             osd_get_pen(pens[j],&r1,&g1,&b1);
  294.             pen = find_pen( (r1*(i+1))>>8, (g1*(i+1))>>8, (b1*(i+1))>>8 );
  295.             for (n = 0; n < h; n++ )
  296.             {
  297.                 Tinten(i + n, j) = pen;
  298.             }
  299.         }
  300.     }
  301.  
  302.     /* build merge color table */
  303.     for( i = 0; i < total_colors ;i++ )                /* color1 */
  304.     {
  305.         unsigned char rgb1[3],rgb2[3];
  306.  
  307.         osd_get_pen(pens[i],&rgb1[0],&rgb1[1],&rgb1[2]);
  308.         for( j = 0; j <= i ;j++ )               /* color2 */
  309.         {
  310.             osd_get_pen(pens[j],&rgb2[0],&rgb2[1],&rgb2[2]);
  311.  
  312.             for (k = 0; k < 3; k++)
  313.             if (translucency) /* add gun values */
  314.             {
  315.                 int tmp;
  316.                 tmp = rgb1[k] + rgb2[k];
  317.                 if (tmp > 255)
  318.                     c[k] = 255;
  319.                 else
  320.                     c[k] = tmp;
  321.             }
  322.             else /* choose highest gun value */
  323.             {
  324.                 if (rgb1[k] > rgb2[k])
  325.                     c[k] = rgb1[k];
  326.                 else
  327.                     c[k] = rgb2[k];
  328.             }
  329.             Tmerge(i,j) = Tmerge(j,i) = find_pen(c[0],c[1],c[2]);
  330.         }
  331.     }
  332.  
  333.     /* build gamma correction table */
  334.     vector_set_gamma (gamma_correction);
  335.  
  336.     return 0;
  337. }
  338.  
  339.  
  340. /*
  341.  * Setup scaling. Currently the Sega games are stuck at VECSHIFT 15
  342.  * and the the AVG games at VECSHIFT 16
  343.  */
  344. void vector_set_shift (int shift)
  345. {
  346.     vecshift = shift;
  347. }
  348.  
  349. /*
  350.  * Clear the old bitmap. Delete pixel for pixel, this is faster than memset.
  351.  */
  352. static void vector_clear_pixels (void)
  353. {
  354.     unsigned char bg=pens[0];
  355.     int i;
  356.     int coords;
  357.  
  358.  
  359.     for (i=p_index-1; i>=0; i--)
  360.     {
  361.         coords = pixel[i];
  362.         vector_pp (vecbitmap, coords >> 16, coords & 0x0000ffff, bg);
  363.     }
  364.  
  365.     p_index=0;
  366.  
  367. }
  368.  
  369. /*
  370.  * Stop the vector video hardware emulation. Free memory.
  371.  */
  372. void vector_vh_stop (void)
  373. {
  374.     if (pTcosin)
  375.         free (pTcosin);
  376.     pTcosin = NULL;
  377.     if (pTinten)
  378.         free (pTinten);
  379.     pTinten = NULL;
  380.     if (pTmerge)
  381.         free (pTmerge);
  382.     pTmerge = NULL;
  383.     if (pixel)
  384.         free (pixel);
  385.     pixel = NULL;
  386.     if (old_list)
  387.         free (old_list);
  388.     old_list = NULL;
  389.     if (new_list)
  390.         free (new_list);
  391.     new_list = NULL;
  392. }
  393.  
  394. /*
  395.  * draws an anti-aliased pixel (blends pixel with background)
  396.  */
  397. INLINE void vector_draw_aa_pixel (int x, int y, int col, int dirty)
  398. {
  399.     if (x < xmin || x >= xmax)
  400.         return;
  401.     if (y < ymin || y >= ymax)
  402.         return;
  403.  
  404.     vector_pp (vecbitmap, x, y, pens[Tmerge(invpens[vector_rp(vecbitmap, x, y)], col)]);
  405.  
  406.     if (p_index<MAX_PIXELS)
  407.     {
  408.         pixel[p_index] = y | (x << 16);
  409.         p_index++;
  410.     }
  411.  
  412.     /* Mark this pixel as dirty */
  413.     if (dirty)
  414.         osd_mark_vector_dirty (x, y);
  415. }
  416.  
  417.  
  418. /*
  419.  * draws a line
  420.  *
  421.  * input:   x2  16.16 fixed point
  422.  *          y2  16.16 fixed point
  423.  *         col  0-255 indexed color (8 bit)
  424.  *   intensity  0-255 intensity
  425.  *       dirty  bool  mark the pixels as dirty while plotting them
  426.  *
  427.  * written by Andrew Caldwell
  428.  */
  429.  
  430. void vector_draw_to (int x2, int y2, int col, int intensity, int dirty)
  431. {
  432.     unsigned char a1;
  433.     int orientation;
  434.     int dx,dy,sx,sy,cx,cy,width;
  435.     static int x1,yy1;
  436.     int xx,yy;
  437.  
  438. #if 0
  439.     logerror("line:%d,%d nach %d,%d color %d\n",x1,yy1,x2,y2,col);
  440. #endif
  441.  
  442.     /* [1] scale coordinates to display */
  443.  
  444.     x2 = vec_mult(x2<<4,vector_scale_x);
  445.     y2 = vec_mult(y2<<4,vector_scale_y);
  446.  
  447.     /* [2] fix display orientation */
  448.  
  449.     orientation = Machine->orientation;
  450.     if (orientation & ORIENTATION_SWAP_XY)
  451.     {
  452.         int temp;
  453.         temp = x2;
  454.         x2 = y2;
  455.         y2 = temp;
  456.     }
  457.     if (orientation & ORIENTATION_FLIP_X)
  458.         x2 = ((vecwidth-1)<<16)-x2;
  459.     if (orientation & ORIENTATION_FLIP_Y)
  460.         y2 = ((vecheight-1)<<16)-y2;
  461.  
  462.     /* [3] adjust cords if needed */
  463.  
  464.     if (antialias)
  465.     {
  466.         if(beam_diameter_is_one)
  467.         {
  468.             x2 = (x2+0x8000)&0xffff0000;
  469.             y2 = (y2+0x8000)&0xffff0000;
  470.         }
  471.     }
  472.     else /* noantialiasing */
  473.     {
  474.         x2 >>= 16;
  475.         y2 >>= 16;
  476.     }
  477.  
  478.     /* [4] handle color and intensity */
  479.  
  480.     if (intensity == 0) goto end_draw;
  481.  
  482.     col = Tinten(intensity,col);
  483.  
  484.     /* [5] draw line */
  485.  
  486.     if (antialias)
  487.     {
  488.         /* draw an anti-aliased line */
  489.         dx=abs(x1-x2);
  490.         dy=abs(yy1-y2);
  491.         if (dx>=dy)
  492.         {
  493.             sx = ((x1 <= x2) ? 1:-1);
  494.             sy = vec_div(y2-yy1,dx);
  495.             if (sy<0)
  496.                 dy--;
  497.             x1 >>= 16;
  498.             xx = x2>>16;
  499.             width = vec_mult(beam<<4,Tcosin(abs(sy)>>5));
  500.             if (!beam_diameter_is_one)
  501.                 yy1-= width>>1; /* start back half the diameter */
  502.             for (;;)
  503.             {
  504.                 dx = width;    /* init diameter of beam */
  505.                 dy = yy1>>16;
  506.                 vector_draw_aa_pixel(x1,dy++,Tinten(Tgammar[0xff&(yy1>>8)],col), dirty);
  507.                 dx -= 0x10000-(0xffff & yy1); /* take off amount plotted */
  508.                 a1 = Tgamma[(dx>>8)&0xff];   /* calc remainder pixel */
  509.                 dx >>= 16;                   /* adjust to pixel (solid) count */
  510.                 while (dx--)                 /* plot rest of pixels */
  511.                     vector_draw_aa_pixel(x1,dy++,col, dirty);
  512.                 vector_draw_aa_pixel(x1,dy,Tinten(a1,col), dirty);
  513.                 if (x1 == xx) break;
  514.                 x1+=sx;
  515.                 yy1+=sy;
  516.             }
  517.         }
  518.         else
  519.         {
  520.             sy = ((yy1 <= y2) ? 1:-1);
  521.             sx = vec_div(x2-x1,dy);
  522.             if (sx<0)
  523.                 dx--;
  524.             yy1 >>= 16;
  525.             yy = y2>>16;
  526.             width = vec_mult(beam<<4,Tcosin(abs(sx)>>5));
  527.             if( !beam_diameter_is_one )
  528.                 x1-= width>>1; /* start back half the width */
  529.             for (;;)
  530.             {
  531.                 dy = width;    /* calc diameter of beam */
  532.                 dx = x1>>16;
  533.                 vector_draw_aa_pixel(dx++,yy1,Tinten(Tgammar[0xff&(x1>>8)],col), dirty);
  534.                 dy -= 0x10000-(0xffff & x1); /* take off amount plotted */
  535.                 a1 = Tgamma[(dy>>8)&0xff];   /* remainder pixel */
  536.                 dy >>= 16;                   /* adjust to pixel (solid) count */
  537.                 while (dy--)                 /* plot rest of pixels */
  538.                     vector_draw_aa_pixel(dx++,yy1,col, dirty);
  539.                 vector_draw_aa_pixel(dx,yy1,Tinten(a1,col), dirty);
  540.                 if (yy1 == yy) break;
  541.                 yy1+=sy;
  542.                 x1+=sx;
  543.             }
  544.         }
  545.     }
  546.     else /* use good old Bresenham for non-antialiasing 980317 BW */
  547.     {
  548.         dx = abs(x1-x2);
  549.         dy = abs(yy1-y2);
  550.         sx = (x1 <= x2) ? 1: -1;
  551.         sy = (yy1 <= y2) ? 1: -1;
  552.         cx = dx/2;
  553.         cy = dy/2;
  554.  
  555.         if (dx>=dy)
  556.         {
  557.             for (;;)
  558.             {
  559.                 vector_draw_aa_pixel (x1, yy1, col, dirty);
  560.                 if (x1 == x2) break;
  561.                 x1 += sx;
  562.                 cx -= dy;
  563.                 if (cx < 0)
  564.                 {
  565.                     yy1 += sy;
  566.                     cx += dx;
  567.                 }
  568.             }
  569.         }
  570.         else
  571.         {
  572.             for (;;)
  573.             {
  574.                 vector_draw_aa_pixel (x1, yy1, col, dirty);
  575.                 if (yy1 == y2) break;
  576.                 yy1 += sy;
  577.                 cy -= dx;
  578.                 if (cy < 0)
  579.                 {
  580.                     x1 += sx;
  581.                     cy += dy;
  582.                 }
  583.             }
  584.         }
  585.     }
  586.  
  587. end_draw:
  588.  
  589.     x1=x2;
  590.     yy1=y2;
  591. }
  592.  
  593.  
  594. /*
  595.  * Adds a line end point to the vertices list. The vector processor emulation
  596.  * needs to call this.
  597.  */
  598. void vector_add_point (int x, int y, int color, int intensity)
  599. {
  600.     point *new;
  601.  
  602.     intensity *= intensity_correction;
  603.     if (intensity > 0xff)
  604.         intensity = 0xff;
  605.  
  606.     if (flicker && (intensity > 0))
  607.     {
  608.         intensity += (intensity * (0x80-(rand()&0xff)) * flicker)>>16;
  609.         if (intensity < 0)
  610.             intensity = 0;
  611.         if (intensity > 0xff)
  612.             intensity = 0xff;
  613.     }
  614.     new = &new_list[new_index];
  615.     new->x = x;
  616.     new->y = y;
  617.     new->col = color;
  618.     new->intensity = intensity;
  619.     new->status = VDIRTY; /* mark identical lines as clean later */
  620.  
  621.     new_index++;
  622.     if (new_index >= MAX_POINTS)
  623.     {
  624.         new_index--;
  625.         logerror("*** Warning! Vector list overflow!\n");
  626.     }
  627. }
  628.  
  629. /*
  630.  * Add new clipping info to the list
  631.  */
  632. void vector_add_clip (int x1, int yy1, int x2, int y2)
  633. {
  634.     point *new;
  635.  
  636.     new = &new_list[new_index];
  637.     new->x = x1;
  638.     new->y = yy1;
  639.     new->arg1 = x2;
  640.     new->arg2 = y2;
  641.     new->status = VCLIP;
  642.  
  643.     new_index++;
  644.     if (new_index >= MAX_POINTS)
  645.     {
  646.         new_index--;
  647.         logerror("*** Warning! Vector list overflow!\n");
  648.     }
  649. }
  650.  
  651.  
  652. /*
  653.  * Set the clipping area
  654.  */
  655. void vector_set_clip (int x1, int yy1, int x2, int y2)
  656. {
  657.     int orientation;
  658.     int tmp;
  659.  
  660.     /* failsafe */
  661.     if ((x1 >= x2) || (yy1 >= y2))
  662.     {
  663.         logerror("Error in clipping parameters.\n");
  664.         xmin = 0;
  665.         ymin = 0;
  666.         xmax = vecwidth;
  667.         ymax = vecheight;
  668.         return;
  669.     }
  670.  
  671.     /* scale coordinates to display */
  672.     x1 = vec_mult(x1<<4,vector_scale_x);
  673.     yy1 = vec_mult(yy1<<4,vector_scale_y);
  674.     x2 = vec_mult(x2<<4,vector_scale_x);
  675.     y2 = vec_mult(y2<<4,vector_scale_y);
  676.  
  677.     /* fix orientation */
  678.     orientation = Machine->orientation;
  679.     /* swapping x/y coordinates will still have the minima in x1,yy1 */
  680.     if (orientation & ORIENTATION_SWAP_XY)
  681.     {
  682.         tmp = x1; x1 = yy1; yy1 = tmp;
  683.         tmp = x2; x2 = y2; y2 = tmp;
  684.     }
  685.     /* don't forget to swap x1,x2, since x2 becomes the minimum */
  686.     if (orientation & ORIENTATION_FLIP_X)
  687.     {
  688.         x1 = ((vecwidth-1)<<16)-x1;
  689.         x2 = ((vecwidth-1)<<16)-x2;
  690.         tmp = x1; x1 = x2; x2 = tmp;
  691.     }
  692.     /* don't forget to swap yy1,y2, since y2 becomes the minimum */
  693.     if (orientation & ORIENTATION_FLIP_Y)
  694.     {
  695.         yy1 = ((vecheight-1)<<16)-yy1;
  696.         y2 = ((vecheight-1)<<16)-y2;
  697.         tmp = yy1; yy1 = y2; y2 = tmp;
  698.     }
  699.  
  700.     xmin = x1 >> 16;
  701.     ymin = yy1 >> 16;
  702.     xmax = x2 >> 16;
  703.     ymax = y2 >> 16;
  704.  
  705.     /* Make it foolproof by trapping rounding errors */
  706.     if (xmin < 0) xmin = 0;
  707.     if (ymin < 0) ymin = 0;
  708.     if (xmax > vecwidth) xmax = vecwidth;
  709.     if (ymax > vecheight) ymax = vecheight;
  710. }
  711.  
  712.  
  713. /*
  714.  * The vector CPU creates a new display list. We save the old display list,
  715.  * but only once per refresh.
  716.  */
  717. void vector_clear_list (void)
  718. {
  719.     point *tmp;
  720.  
  721.     if (vector_runs == 0)
  722.     {
  723.         old_index = new_index;
  724.         tmp = old_list; old_list = new_list; new_list = tmp;
  725.     }
  726.  
  727.     new_index = 0;
  728.     vector_runs++;
  729. }
  730.  
  731.  
  732. /*
  733.  * By comparing with the last drawn list, we can prevent that identical
  734.  * vectors are marked dirty which appeared at the same list index in the
  735.  * previous frame. BW 19980307
  736.  */
  737. static void clever_mark_dirty (void)
  738. {
  739.     int i, j, min_index, last_match = 0;
  740.     unsigned int *coords;
  741.     point *new, *old;
  742.     point newclip, oldclip;
  743.     int clips_match = 1;
  744.  
  745.     if (old_index < new_index)
  746.         min_index = old_index;
  747.     else
  748.         min_index = new_index;
  749.  
  750.     /* Reset the active clips to invalid values */
  751.     memset (&newclip, 0, sizeof (newclip));
  752.     memset (&oldclip, 0, sizeof (oldclip));
  753.  
  754.     /* Mark vectors which are not the same in both lists as dirty */
  755.     new = new_list;
  756.     old = old_list;
  757.  
  758.     for (i = min_index; i > 0; i--, old++, new++)
  759.     {
  760.         /* If this is a clip, we need to determine if the clip regions still match */
  761.         if (old->status == VCLIP || new->status == VCLIP)
  762.         {
  763.             if (old->status == VCLIP)
  764.                 oldclip = *old;
  765.             if (new->status == VCLIP)
  766.                 newclip = *new;
  767.             clips_match = (newclip.x == oldclip.x) && (newclip.y == oldclip.y) && (newclip.arg1 == oldclip.arg1) && (newclip.arg2 == oldclip.arg2);
  768.             if (!clips_match)
  769.                 last_match = 0;
  770.  
  771.             /* fall through to erase the old line if this is not a clip */
  772.             if (old->status == VCLIP)
  773.                 continue;
  774.         }
  775.  
  776.         /* If the clips match and the vectors match, update */
  777.         else if (clips_match && (new->x == old->x) && (new->y == old->y) &&
  778.             (new->col == old->col) && (new->intensity == old->intensity))
  779.         {
  780.             if (last_match)
  781.             {
  782.                 new->status = VCLEAN;
  783.                 continue;
  784.             }
  785.             last_match = 1;
  786.         }
  787.  
  788.         /* If nothing matches, remember it */
  789.         else
  790.             last_match = 0;
  791.  
  792.         /* mark the pixels of the old vector dirty */
  793.         coords = &pixel[old->arg1];
  794.         for (j = (old->arg2 - old->arg1); j > 0; j--)
  795.         {
  796.             osd_mark_vector_dirty (*coords >> 16, *coords & 0x0000ffff);
  797.             coords++;
  798.         }
  799.     }
  800.  
  801.     /* all old vector with index greater new_index are dirty */
  802.     /* old = &old_list[min_index] here! */
  803.     for (i = (old_index-min_index); i > 0; i--, old++)
  804.     {
  805.         /* skip old clips */
  806.         if (old->status == VCLIP)
  807.             continue;
  808.  
  809.         /* mark the pixels of the old vector dirty */
  810.         coords = &pixel[old->arg1];
  811.         for (j = (old->arg2 - old->arg1); j > 0; j--)
  812.         {
  813.             osd_mark_vector_dirty (*coords >> 16, *coords & 0x0000ffff);
  814.             coords++;
  815.         }
  816.     }
  817. }
  818.  
  819. void vector_vh_update(struct osd_bitmap *bitmap,int full_refresh)
  820. {
  821.     int i;
  822.     int temp_x, temp_y;
  823.     point *new;
  824.  
  825.     /* copy parameters */
  826.     vecbitmap = bitmap;
  827.     vecwidth  = bitmap->width;
  828.     vecheight = bitmap->height;
  829.  
  830.     /* setup scaling */
  831.     temp_x = (1<<(44-vecshift)) / (Machine->drv->visible_area.max_x - Machine->drv->visible_area.min_x);
  832.     temp_y = (1<<(44-vecshift)) / (Machine->drv->visible_area.max_y - Machine->drv->visible_area.min_y);
  833.  
  834.     if (Machine->orientation & ORIENTATION_SWAP_XY)
  835.     {
  836.         vector_scale_x = temp_x * vecheight;
  837.         vector_scale_y = temp_y * vecwidth;
  838.     }
  839.     else
  840.     {
  841.         vector_scale_x = temp_x * vecwidth;
  842.         vector_scale_y = temp_y * vecheight;
  843.     }
  844.     /* reset clipping area */
  845.     xmin = 0; xmax = vecwidth; ymin = 0; ymax = vecheight;
  846.  
  847.     /* next call to vector_clear_list() is allowed to swap the lists */
  848.     vector_runs = 0;
  849.  
  850.     /* mark pixels which are not idential in newlist and oldlist dirty */
  851.     /* the old pixels which get removed are marked dirty immediately,  */
  852.     /* new pixels are recognized by setting new->dirty                 */
  853.     clever_mark_dirty();
  854.  
  855.     /* clear ALL pixels in the hidden map */
  856.     vector_clear_pixels();
  857.  
  858.     /* Draw ALL lines into the hidden map. Mark only those lines with */
  859.     /* new->dirty = 1 as dirty. Remember the pixel start/end indices  */
  860.     new = new_list;
  861.     for (i = 0; i < new_index; i++)
  862.     {
  863.         if (new->status == VCLIP)
  864.             vector_set_clip (new->x, new->y, new->arg1, new->arg2);
  865.         else
  866.         {
  867.             new->arg1 = p_index;
  868.             vector_draw_to (new->x, new->y, new->col, Tgamma[new->intensity], new->status);
  869.  
  870.             new->arg2 = p_index;
  871.         }
  872.         new++;
  873.     }
  874. }
  875.  
  876. /*********************************************************************
  877.   Artwork functions.
  878.  *********************************************************************/
  879.  
  880. /*********************************************************************
  881.   Restore the old bitmap with the artwork (backdrop or overlay).
  882.   MLR 100598
  883.  *********************************************************************/
  884.  
  885. static void vector_restore_artwork (struct osd_bitmap *bitmap, struct artwork *a, int full_refresh)
  886. {
  887.     int i, x, y;
  888.     struct osd_bitmap *artwork;
  889.  
  890.     if (full_refresh)
  891.     {
  892.         copybitmap(bitmap, a->artwork ,0,0,0,0,NULL,TRANSPARENCY_NONE,0);
  893.         osd_mark_dirty (0, 0, bitmap->width, bitmap->height, 0);
  894.     }
  895.     else if (pixel)
  896.     {
  897.         artwork = a->artwork;
  898.  
  899.         for (i=p_index-1; i>=0; i--)
  900.         {
  901.             x = pixel[i] >> 16;
  902.             y = pixel[i] & 0x0000ffff;
  903.             vector_pp (bitmap, x, y, vector_rp(artwork, x, y));
  904.         }
  905.     }
  906. }
  907.  
  908. /*********************************************************************
  909.   vector_vh_update_backdrop
  910.  
  911.   This draws a vector screen with backdrop.
  912.  
  913.   First the backdrop is restored. Then the new vector screen
  914.   is recalculated with vector_vh_update. Changed pixels are
  915.   then merged with the backdrop.
  916.  *********************************************************************/
  917.  
  918. static void vector_vh_update_backdrop(struct osd_bitmap *bitmap, struct artwork *a, int full_refresh)
  919. {
  920.     int i, x, y;
  921.     unsigned int coords;
  922.     int newcol, bdcol;
  923.     UINT8 r, g, b, rb, gb, bb;
  924.     struct osd_bitmap *vb = a->vector_bitmap;
  925.     struct osd_bitmap *ob = a->orig_artwork;
  926.     struct osd_bitmap *ab = a->artwork;
  927.     UINT8 *tab = a->pTable;
  928.     UINT8 *brightness = a->brightness;
  929.     vector_restore_artwork(bitmap, a, full_refresh);
  930.     vector_vh_update(vb, full_refresh);
  931.  
  932.     if (bitmap->depth == 8)
  933.         for (i = p_index - 1; i >= 0; i--)
  934.         {
  935.             coords = pixel[i];
  936.             x = coords >> 16;
  937.             y = coords & 0x0000ffff;
  938.             newcol = pens[tab[vector_rp(ob, x, y) * total_colors + invpens[vector_rp(vb, x, y)]]];
  939.             if (brightness[newcol] > brightness[vector_rp(ab, x, y)])
  940.                 vector_pp (bitmap, x, y, newcol);
  941.         }
  942.     else
  943.         for (i = p_index - 1; i >= 0; i--)
  944.         {
  945.             coords = pixel[i];
  946.             x = coords >> 16;
  947.             y = coords & 0x0000ffff;
  948.  
  949.             osd_get_pen (vector_rp(vb, x, y), &r, &g, &b);
  950.             bdcol = vector_rp(ab, x, y);
  951.             osd_get_pen (bdcol, &rb, &gb, &bb);
  952.             r = MIN (255, r + rb / 4);
  953.             g = MIN (255, g + gb / 4);
  954.             b = MIN (255, b + bb / 4);
  955.             newcol = Machine->pens[(((r & 0xf8) << 7) | ((g & 0xf8) << 2) | (b >> 3)) + a->start_pen];
  956.             if (brightness[newcol] > brightness[bdcol])
  957.                 vector_pp (bitmap, x, y, newcol);
  958.         }
  959. }
  960.  
  961. void vector_vh_screenrefresh(struct osd_bitmap *bitmap,int full_refresh)
  962. {
  963.     if (artwork_backdrop)
  964.         vector_vh_update_backdrop(bitmap, artwork_backdrop, full_refresh);
  965.     else
  966.         vector_vh_update(bitmap, full_refresh);
  967. }
  968.  
  969. #endif /* if !(defined xgl) && !(defined xfx) && !(defined svgafx) */
  970.